/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.logiclander.whozwho.data.dao.hibernate;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.notNull;
import static com.logiclander.whozwho.data.dao.SystemDto.EMPTY_SYSTEM_DTO;
import static java.lang.String.format;

import com.logiclander.whozwho.data.dao.SystemDao;
import com.logiclander.whozwho.data.dao.SystemDto;
import java.util.Date;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

/**
 *
 * @author logiclander
 */
public class SystemDaoImpl implements SystemDao {

  private SessionFactory sessionFactory;

  public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = checkNotNull(sessionFactory,
            "Required sessionFactory cannot be set to null.");
  }

  @Override
  public SystemDto createSystem(String name) {
    checkState(notNull().apply(sessionFactory),
            "sessionFactory property was not set.");

    System s = retrieveSystem("name", name);

    if (notNull().apply(s)) {
//already exists... what to do?  error or return it or what?
      name = s.getName();

    } else {

      Session session = sessionFactory.getCurrentSession();
      session.beginTransaction();

      s = new System();
      s.setName(name);

      Long sid = (Long) session.save(s);
      session.getTransaction().commit();

      s.setSid(sid);
    }

    return toSystemDto(s);
  }

  @Override
  public SystemDto getSystemBySid(Long sid) {
    SystemDto sDto = EMPTY_SYSTEM_DTO;

    System s = retrieveSystem("sid", sid);

    if (notNull().apply(s)) {
      sDto = toSystemDto(s);
    }

    return sDto;
  }

  @Override
  public List<SystemDto> getSystems() {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public List<SystemDto> getSystemsBySidFilter(String sidFilter) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public SystemDto getSystemByTitle(String title) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public List<SystemDto> getSystemsByTitleFilter(String titleFilter) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public void putSystem(SystemDto system) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public Boolean expireSystem(Long sid) {
    Boolean expired = Boolean.FALSE;

    System s = retrieveSystem("sid", sid);

    if (notNull().apply(s)) {
      s.setExpired(new Date());
      updateSystem(s);
      expired = Boolean.TRUE;
    }

    return expired;
  }

  private System retrieveSystem(String paramName, Object paramValue) {

    checkState(notNull().apply(sessionFactory),
            "sessionFactory property was not set.");

    Session session = sessionFactory.getCurrentSession();
    session.beginTransaction();

    System s = (System) session.createQuery(generateHql(paramName)).setParameter(paramName, paramValue).uniqueResult();
    session.getTransaction().commit();

    return s;
  }

  private void updateSystem(System s) {

    checkState(notNull().apply(sessionFactory),
            "sessionFactory property was not set.");

    Session session = sessionFactory.getCurrentSession();
    session.beginTransaction();
    session.update(s);
    session.getTransaction().commit();
  }

  private SystemDto toSystemDto(System s) {

    SystemDto.Builder sDto =
            SystemDto.builder();

    if (notNull().apply(s.getSid())) {
      sDto.sid(s.getSid());
    }

    if (notNull().apply(s.getName())) {
      sDto.title(s.getName());
    }

		if (notNull().apply(s.getExpired())) {
			sDto.expired(s.getExpired());
		}

    return sDto.build();
  }

  private String generateHql(String paramName) {
    return format("from System a where a.%s = :%s and a.expired is null",
                  paramName, paramName);
  }

}
